Amazon CloudWatch ロググループに対して ABAC 用タグがある場合は ABAC により読み取り許可を制御して、ABAC 用タグがない場合は読み取りを許可するポリシーを試してみた

Amazon CloudWatch ロググループに対して ABAC 用タグがある場合は ABAC により読み取り許可を制御して、ABAC 用タグがない場合は読み取りを許可するポリシーを試してみた

Clock Icon2024.10.04

Amazon CloudWatch Logs に対してログの読み取りを ABAC で制御したいが、ABAC 用のタグが付与されていないロググループに対しては閲覧を許可したいと思い、その確認結果をブログにします。

本ブログで試したポリシーのイメージ図です。

abac-in-amazon-cloudwatch-logs-2

今回は IAM ロールを利用しており、IAM ロールには ABAC 用のタグとして Project: aaa を設定しています。Amazon CloudWatch Logs 側はタグがないロググループと Project: aaaProject: bbb タグが付与されたロググループがあるとします。その場合において、Project タグがあるロググループに対しては ABAC により IAM ロールの Project タグと同じ値を持つロググループだけ読み取りでき、Project タグが付与されていないロググループは無条件で読み取りできます。

具体的な IAM ポリシーとしては、次の内容になります。ReadOnlyAccess などの CloudWatch Logs の読み取り権限があるポリシーと併用して利用する前提です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "logs:Get*",
                "logs:FilterLogEvents",
                "logs:StartQuery",
                "logs:StopQuery",
                "logs:StartLiveTail",
                "logs:StopLiveTail",
                "logs:TestMetricFilter"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:*",
            "Condition": {
                "Null": {
                    "aws:ResourceTag/Project": "false"
                },
                "StringNotEquals": {
                    "aws:ResourceTag/Project": "${aws:PrincipalTag/Project}"
                }
            }
        }
    ]
}

Condition の Null 条件で CloudWatch Logs ロググループに Project タグが存在していることを確認し、StringNotEquals 条件でロググループの Project タグの値と IAM ロール の Project タグの値の一致を確認します。Project タグがないロググループは Null 条件の条件に一致しないため Deny が行われません。

以降では、CloudWatch Logs のテストデータを作成して、実際に上記のポリシーの動作の一部を確認してみたいと思います。

CloudWatch Logs のテストデータ準備

テスト用に次の CloudWatch Logs のデータを作成します。キー名が「Project」のタグが ABAC に利用するタグとなります。

ロググループ名 Project タグ
/test/abac/log なし
/test/abac/log-aaa Project: aaa
/test/abac/log-bbb Project: bbb

ロググループを作成するコマンドです。

aws logs create-log-group \
  --log-group-name /test/abac/log
aws logs create-log-group \
  --log-group-name /test/abac/log-aaa \
  --tags Project=aaa
aws logs create-log-group \
  --log-group-name /test/abac/log-bbb \
  --tags Project=bbb

ログストリームとテストメッセージを作成するコマンドです。

aws logs create-log-stream \
  --log-group-name /test/abac/log \
  --log-stream-name test-log-stream
aws logs put-log-events \
  --log-group-name /test/abac/log \
  --log-stream-name test-log-stream \
  --log-events "[{\"timestamp\": $(date +%s%N | cut -b1-13), \"message\": \"This is a test message\"}]"
aws logs create-log-stream \
  --log-group-name /test/abac/log-aaa \
  --log-stream-name test-log-aaa-stream
aws logs put-log-events \
  --log-group-name /test/abac/log-aaa \
  --log-stream-name test-log-aaa-stream \
  --log-events "[{\"timestamp\": $(date +%s%N | cut -b1-13), \"message\": \"This is a test message\"}]"
aws logs create-log-stream \
  --log-group-name /test/abac/log-bbb \
  --log-stream-name test-log-bbb-stream
aws logs put-log-events \
  --log-group-name /test/abac/log-bbb \
  --log-stream-name test-log-bbb-stream \
  --log-events "[{\"timestamp\": $(date +%s%N | cut -b1-13), \"message\": \"This is a test message\"}]"

以上で、テストデータの作成は終わります。

IAM ロールの作成

テスト用のログにアクセスする IAM ロールを作成します。

項目 設定値 備考
ロール名 test-abac-role
許可ポリシー - AWS 管理ポリシー ReadOnlyAccess CloudWatch Logs の読み取り権限を包含
許可ポリシー - カスタマー管理ポリシー test-abac-policy ポリシーは下記参照
信頼ポリシー (記載を省略)
タグ Project: aaa ABAC に利用

test-abac-policy のポリシーです。ブログの冒頭で紹介した内容と同じポリシーです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "logs:Get*",
                "logs:FilterLogEvents",
                "logs:StartQuery",
                "logs:StopQuery",
                "logs:StartLiveTail",
                "logs:StopLiveTail",
                "logs:TestMetricFilter"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:*",
            "Condition": {
                "Null": {
                    "aws:ResourceTag/Project": "false"
                },
                "StringNotEquals": {
                    "aws:ResourceTag/Project": "${aws:PrincipalTag/Project}"
                }
            }
        }
    ]
}

Conditon の Null 条件と StringNotEquals 条件は AND 条件となっています。Null 条件で CloudWatch Logs ロググループに Project タグが存在していることを確認します。StringNotEquals 条件でロググループの Project タグの値と IAM プリンシパル(今回は IAM ロール)の Project タグの値の一致を確認します。

Null 条件と ABAC の条件式はそれぞれ次のブログの解説が参考になります。

https://dev.classmethod.jp/articles/aws-iam-condition-null-tukaimichi/

https://dev.classmethod.jp/articles/akibaaws-06-iam-abac/

動作確認

作成した IAM ロールにスイッチロールして事前に作成した 3 種類の CloudWatch ロググループにアクセスしてみます。

ロググループ名 Project タグ 想定動作
/test/abac/log なし ログを閲覧できる
/test/abac/log-aaa Project: aaa ログを閲覧できる
/test/abac/log-bbb Project: bbb ログを閲覧できない

なお、確認したアクションはログストリーム内のログの取得とインサイトの利用のみであり、テーリングとメトリクスフィルターのテストについては確認しておりません。ご注意ください。

Project タグがないロググループにアクセス

タグがないロググループである /test/abac/log のログストームを確認できました。

$ aws logs describe-log-streams --log-group-name /test/abac/log
{
    "logStreams": [
        {
            "logStreamName": "test-log-stream",
            "creationTime": 1727968080773,
            "firstEventTimestamp": 1727968083104,
            "lastEventTimestamp": 1727968083104,
            "lastIngestionTime": 1727968084198,
            "uploadSequenceToken": "49039859604571996806275410876608648010988706915264864394",
            "arn": "arn:aws:logs:ap-northeast-1:111122223333:log-group:/test/abac/log:log-stream:test-log-stream",
            "storedBytes": 0
        }
    ]
}

ログストーム内のログも確認できました。

$ aws logs get-log-events --log-group-name /test/abac/log --log-stream-name test-log-stream
{
    "events": [
        {
            "timestamp": 1727968083104,
            "message": "This is a test message",
            "ingestionTime": 1727968084198
        }
    ],
    "nextForwardToken": "f/38534975932495692789411082818793199302787112822650699776/s",
    "nextBackwardToken": "b/38534975932495692789411082818793199302787112822650699776/s"
}

マネジメントコンソールにおいてもログの内容を確認できました。

abac-in-amazon-cloudwatch-logs-6

ログのインサイトで検索することもできました。

abac-in-amazon-cloudwatch-logs-7-2

Project: aaa タグのロググループにアクセス

Project: aaa タグが付与されているロググループである /test/abac/log-aaa においてログストームを確認できました。

$ aws logs describe-log-streams --log-group-name /test/abac/log-aaa
{
    "logStreams": [
        {
            "logStreamName": "test-log-aaa-stream",
            "creationTime": 1727968087423,
            "firstEventTimestamp": 1727968091153,
            "lastEventTimestamp": 1727968091153,
            "lastIngestionTime": 1727968092057,
            "uploadSequenceToken": "49039859604572007252678305413435984984923135507524530828",
            "arn": "arn:aws:logs:ap-northeast-1:111122223333:log-group:/test/abac/log-aaa:log-stream:test-log-aaa-stream",
            "storedBytes": 0
        }
    ]
}

ログストーム内のログも確認できました。

$ aws logs get-log-events --log-group-name /test/abac/log-aaa --log-stream-name test-log-aaa-stream
{
    "events": [
        {
            "timestamp": 1727968091153,
            "message": "This is a test message",
            "ingestionTime": 1727968092057
        }
    ],
    "nextForwardToken": "f/38534976111994390892384068494515486485664399480845697024/s",
    "nextBackwardToken": "b/38534976111994390892384068494515486485664399480845697024/s"
}

マネジメントコンソールにおいてもログの内容を確認できました。

abac-in-amazon-cloudwatch-logs-4

ログのインサイトで検索することもできました。

abac-in-amazon-cloudwatch-logs-5-2

Project: bbb タグのロググループにアクセス

Project: bbb タグが付与されているロググループである /test/abac/log-bbb においてもログストームは確認できました。

$ aws logs describe-log-streams --log-group-name /test/abac/log-bbb
{
    "logStreams": [
        {
            "logStreamName": "test-log-bbb-stream",
            "creationTime": 1727968095149,
            "firstEventTimestamp": 1727968097986,
            "lastEventTimestamp": 1727968097986,
            "lastIngestionTime": 1727968099265,
            "uploadSequenceToken": "49039859604572016833753624725061899413445935812087787752",
            "arn": "arn:aws:logs:ap-northeast-1:111122223333:log-group:/test/abac/log-bbb:log-stream:test-log-bbb-stream",
            "storedBytes": 0
        }
    ]
}

ログストリーム内のログは想定通り確認できませんでした。

$ aws logs get-log-events --log-group-name /test/abac/log-bbb --log-stream-name test-log-bbb-stream

An error occurred (AccessDeniedException) when calling the GetLogEvents operation: User: arn:aws:sts::111122223333:assumed-role/test-abac-role/cm-hanazawa.yuki is not authorized to perform: logs:GetLogEvents on resource: arn:aws:logs:ap-northeast-1:111122223333:log-group:/test/abac/log-bbb:log-stream:test-log-bbb-stream with an explicit deny in an identity-based policy

マネジメントコンソールでも確認してみます。
ロググループを選択することでログストリーム名までは閲覧できます。

abac-in-amazon-cloudwatch-logs-1

ログストリームを選択した場合はエラーにより閲覧できません。

abac-in-amazon-cloudwatch-logs-3

ログのインサイト機能も利用できないことを確認できました。

abac-in-amazon-cloudwatch-logs-8

以上で動作確認は終わりです。

さいごに

Amazon CloudWatch Logs において、ABAC 用のタグがある場合のみ ABAC で読み取りを制御し、ABAC 用のタグがない場合は制限なくログを閲覧できるポリシーを試してみました。特定のロググループに重要なデータが含まれる場合に利用できるかもしれません。
また、紹介した IAM ポリシーの Null 条件がない場合は、タグのないロググループも ABAC の制御になります。すべて ABAC で制御したい場合は Deny ではなく Allow で作成する方法もあります。

以上、このブログがどなたかのご参考になれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.